#
#  对结果进行评价的库
# 

import numpy as np
from sklearn import linear_model    # 线性拟合器
import logging
logger = logging.getLogger("mylog")


def stdError_func(y_test, y):
  return np.sqrt(np.mean((y_test - y) ** 2))


def R2_1_func(y_test, y):
  return 1 - ((y_test - y) ** 2).sum() / ((y.mean() - y) ** 2).sum()


def R2_2_func(y_test, y):
  y_mean = np.array(y)
  y_mean[:] = y.mean()
  return 1 - stdError_func(y_test, y) / stdError_func(y_mean, y)

def model_evaluate(err_x,err_predict_y,err_code,evaluation_image_path,drawFlag=True):
    logger.info("使用一次回归方程，评价模型计算精度\n")
    # 使用线性回归方程，评价拟合精度
    # err [sample_lai,err,predict]
    cft = linear_model.LinearRegression()
    cft.fit(err_x[:,np.newaxis],err_predict_y) #模型将x变成二维的形式, 输入的x的维度为[None, 1]
    logger.info("model coefficients\t{}".format(cft.coef_))
    logger.info("model intercept\t{}".format(cft.intercept_))
    predict_y =  cft.predict(err_x[:,np.newaxis])
    strError = stdError_func(predict_y, err_predict_y)
    R2_1 = R2_1_func(predict_y, err_predict_y)
    R2_2 = R2_2_func(predict_y, err_predict_y)
    score = cft.score(err_x[:,np.newaxis], err_predict_y) ##sklearn中自带的模型评估，与R2_1逻辑相同
    logger.info(' strError={:.2f}, R2_1={:.2f},  R2_2={:.2f}, clf.score={:.2f}'.format(strError,R2_1,R2_2,score))
    logger.info("拟合方程：y={}*x+{}".format(cft.coef_,cft.intercept_))
    # 绘制误差图
    # 根据情况判断是否绘制误差图
    if drawFlag:
        from matplotlib import pyplot as plt
        plt.scatter(err_x,err_predict_y,label="ori_pre")
        for i in range(len(err_code)):
            plt.annotate(err_code[i], xy = (err_x[i],err_predict_y[i])) # 这里xy是需要标记的坐标，xytext是对应的标签坐标
            
        plt.plot(err_x,predict_y,label="y={}*x+{}".format(cft.coef_,cft.intercept_))
        plt.plot(np.arange(10),np.arange(10),label="y=x")
        plt.legend()
        plt.savefig(evaluation_image_path,dpi=600)
        plt.show()        
        
    logger.info("\n模型评价结束\n")
    pass
